#include "callback.h"
#include "cfg.h"
#include "conn_event.h"

void evconn_tick_cb(evutil_socket_t fd, short events, void* args)
{
	LOG_DEBUG("listen on %s, %d connected, %d in waiting list",
		gCtx->cfg->listen_addr_str,
		gCtx->connected_conn_count, 
		gCtx->waiting_conn_count);
}

void evconn_stop_cb(evutil_socket_t signal, short event, void* args)
{
	if(signal == EVCONN_STOP_SIGNAL)
	{
		LOG_DEBUG("receive stop signal.");
		gCtx->stop_flag = 1;
	}
}

void evconn_reload_cb(evutil_socket_t signal, short event, void* args)
{
	if(signal == EVCONN_RELOAD_SIGNAL)
	{
		LOG_DEBUG("receive reload signal.");
		gCtx->reload_flag = 1;
	}
}

void evconn_listener_error_cb(struct evconnlistener* listener, void* args)
{
	LOG_FATAL("listener fd=%d, errno=%d, %s",
			evconnlistener_get_fd(listener),
			errno, strerror(errno));

	char filename[64];
	struct timeval now;
	event_base_gettimeofday_cached(evconnlistener_get_base(listener), &now);
	snprintf(filename, sizeof(filename), "eventdump.");
	get_timestamp_suffix(&now, filename + strlen(filename));
	FILE* file = fopen(filename, "w+");
	if(!file) return;
	event_base_dump_events(gCtx->reactor, file);
	fclose(file);
	assert(0);
}

/* listner process: fd is the new file descriptor */
void evconn_listener_cb(struct evconnlistener* listener, evutil_socket_t fd, 
	struct sockaddr* addr, int32_t socklen, void* args)
{
	/* set wait flag */
	gCtx->wait_flag = 0;
	
	LOG_DEBUG("receive new connected socket fd=%d", fd);

	/* check waiting list not full */
	if(gCtx->waiting_conn_count >= gCtx->cfg->max_conn_in_queue)
	{
		LOG_ERROR("current %d connections in queue, can't handle any more, close fd=%d",
			gCtx->waiting_conn_count, fd);
		close(fd);
		return;
	}

	/* initialize a new connection event */
	struct connev_t* connev = connev_pool_alloc_init(gCtx->connev_pool, fd);
	if(!connev)
	{
		LOG_FATAL("connev fd=%d allocate fail, close and ignore", fd);
		close(fd);
		return;
	}

	/* add to reactor */
	if(connev_add(connev) < 0)
		goto ADD_CONNEV_FAIL;

	/* add hash index */
	if(hash_insert(gCtx->connev_table, connev) < 0)
		goto ADD_CONNEV_FAIL;
	
	LOG_DEBUG("add connection-event from %s fd=%d to reactor success", 
			connev_peer_addr(connev), fd);
	return;

ADD_CONNEV_FAIL:
	LOG_ERROR("add connection-event to reactor fail, fd=%d", fd);
	connev_pool_free(gCtx->connev_pool, connev);
}


